package com.scs.application.core.mvc.controller;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.scs.application.core.consts.ErrorCode;
import com.scs.application.core.entity.BaseEntity;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.export.entity.ExportParams;
import com.scs.application.core.export.service.ImportService;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.query.QueryContextHolder;
import com.scs.application.core.service.IBaseService;
import com.scs.application.core.threadLock.ThreadLock;
import com.scs.application.core.utils.CacheUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.sys.model.PageResult;
import com.scs.application.modules.sys.model.RestResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
 * @Description： 基类controller-增删改查
 */
public class CrudController<S extends IBaseService<E>, E extends BaseEntity> extends BaseController {

    @Autowired
    protected S service;

    protected Class<E> currentModelClass() {
        return (Class<E>) ReflectionKit.getSuperClassGenericType(getClass(), 1);
    }
    @Autowired
    private JdbcTemplate jdbcTemplate;
/*
    protected boolean allowCreate(){
        return true;
    }

    protected boolean allowList(){
        return true;
    }

    protected boolean allowUpdate(){
        return true;
    }

    protected boolean allowDelete(){
        return true;
    }
*/

    // 新增后 保存后 填充数据
    public void fillDataForWeb(E entity) {
    }

    /**
     * 获取数据列表
     */
    @GetMapping("/page")
    public PageResult page() {
        QueryContext queryContext = QueryContextHolder.currentContext();
        IPage pageResult = service.page(queryContext);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    @GetMapping("/list")
    public RestResult<List> list() {
        QueryContext queryContext = QueryContextHolder.currentContext();

        List result = service.list(queryContext);
        return RestResult.ok("查询成功", result);
    }

    @GetMapping("/exportFullData")
    public RestResult exportFullData(@RequestParam Map<String, String> reqData) throws Exception {
        QueryContext queryContext = QueryContextHolder.currentContext();
        ExportParams exportParams = JSON.parseObject(JSON.toJSONString(reqData), ExportParams.class);
        Map<String, Object> userParam = null;
        //固定参数
        if (reqData.containsKey("userParam")) {
            JSONObject ob = JSON.parseObject(reqData.get("userParam") + "");
            userParam = Maps.newHashMap(ob);
        }
        String downloadPath = service.exportFullData(queryContext, exportParams, userParam);
        return RestResult.ok("查询成功", downloadPath);
    }

    /**
     * 获取所有数据
     *
     * @param onlyBusFields 仅查询业务字段
     * @return
     */
    @GetMapping("/all")
    public RestResult findAll(@RequestParam(required = false) boolean onlyBusFields) {
        QueryWrapper<E> wrapper = Wrappers.<E>query();
        if (onlyBusFields) {
            ArrayList<String> comFields = Lists.newArrayList("creator", "gmtCreate", "modifier", "gmtModified");
            wrapper.select(currentModelClass(), o -> !comFields.contains(o.getProperty()));
        }

        List<E> models = service.list(wrapper);
        return RestResult.ok("查询成功", models);
    }


    /**
     * 根据ID查找数据
     */
    @GetMapping("/find")
    public RestResult find(@RequestParam("id") Serializable id) {
        E entity = service.getById(id);
        if (entity == null) {
            return RestResult.error("数据查询失败<br>可能所操作数据已被删除，请刷新后重新尝试操作");
        }
        fillDataForWeb(entity);
        return RestResult.ok("获取数据成功", entity);
    }


    /**
     * 添加/更新数据
     */
    @PostMapping("/save")
    public RestResult saveItem(@Valid @RequestBody E entity) {
        boolean isOk = service.saveOrUpdate(entity);
        if (!isOk) {
            return RestResult.error("数据保存失败");
        }
        fillDataForWeb(entity);
        return RestResult.ok("数据保存成功", entity);
    }

    @PostMapping("/saveBatch")
    public RestResult saveBatch(@Valid @RequestBody List<E> entityList) {
        boolean isOk = service.saveOrUpdateBatch(entityList);
        if (!isOk) {
            return RestResult.error("数据保存失败");
        }
        return RestResult.ok("数据保存成功", entityList);
    }


    /**
     * 删除数据
     */
    @DeleteMapping("/delete")
    public RestResult deleteItems(@RequestBody Map<String, Object> para) {
        List<Serializable> ids = (List<Serializable>) para.get("ids");
        Boolean isOk = service.removeCascadeByIds(ids);
        if (!isOk) {
            return RestResult.error("数据删除失败<br>可能所操作数据已被删除，请刷新页面重新尝试操作");
        }
        return RestResult.ok("数据删除成功");
    }

    /**
     * 根据ID查找数据
     */
    @GetMapping("/findBy")
    public RestResult findBy(@RequestParam("key") String key,@RequestParam("value") String value) {
        E entity = service.getOne(Wrappers.<E>query().eq(StringUtils.uncamelCase(key), value).last("limit 1"));
        if (entity == null) {
            return RestResult.error("数据查询失败<br>可能所操作数据已被删除，请刷新后重新尝试操作");
        }
        return RestResult.ok("获取数据成功", entity);
    }

    //顶部合计
    @GetMapping("/sumTop")
    public RestResult sumTop(String sumFields) {
        if (StringUtils.isBlank(sumFields)) return RestResult.ok("查询成功", null);
        return RestResult.ok("查询成功", service.sum(QueryContextHolder.currentContext(),sumFields));
    }

    /**
     * 获取第一条数据 【仅打印预览使用】
     */
    @GetMapping("/getOnlyOne")
    public RestResult getOnlyOne() {
        E entity = service.getOne(Wrappers.<E>query().last("limit 1"));
        if (entity == null) {
            return RestResult.error("数据查询失败<br>一条数据也没找到");
        }
        return RestResult.ok("获取数据成功", entity);
    }

    /**
     * 根据id强制更新字段值【一般情况不要使用】
     */
    @PostMapping("/forceUpdate")
    public RestResult forceUpdate(@RequestBody Map<String, Object> entityMap) {
        if (entityMap != null && entityMap.keySet().size() > 1 && entityMap.containsKey("id")) {
            UpdateWrapper<E> wrapper = Wrappers.<E>update().eq("id", entityMap.get("id"));
            for (String key : entityMap.keySet()) {
                if (key == null ||  "id".equalsIgnoreCase(key)) { continue; }
                wrapper.set(StringUtils.uncamelCase(key), entityMap.get(key));
            }
            if (service.update(wrapper)) {
                return RestResult.ok("数据保存成功", entityMap);
            }
        }
        return RestResult.error("数据保存失败");
    }

    /**
     * 数据视图-导入数据
     */
    @GetMapping("/importData")
    synchronized public RestResult importData(HttpServletResponse response, HttpServletRequest request, @RequestParam Map<String, String> reqData) throws Exception {
        logger.info("matr.import.开始");
        RestResult restResult = RestResult.ok();
        //导入模板视图标识
        String importViewKey = reqData.get("importViewKey");
        //已上传文件路径
        String filePath = reqData.get("filePath");
        String opType = reqData.get("opType");
        String importStamp = reqData.get("importStamp");

        String viewString = CacheUtils.get(CacheUtils.DATAVIEW_CACHE, importViewKey) + "";
        if (StringUtils.isBlank(viewString)) {
            BusinessException.throwError("请稍候，服务器启动中");
        }
        JSONObject dataViewOb = JSONObject.parseObject(viewString);
        JSONArray columnsArr = dataViewOb.getJSONArray("columns");//数据视图dataView定义的列信息的JSON数组
        String tempTableName = "import_temp_" + importViewKey, sql;

        try {
            List<JSONObject> dataList = ImportService.getTableDataFromExcel(filePath, tempTableName, importStamp, columnsArr, dataViewOb);
            logger.debug("importData.数据");
            logger.debug(JSON.toJSONString(dataList));

            restResult.setMsg(service.importData(dataList));
            logger.info("importData.结束");
            logger.info(restResult.getMsg());
        }catch (Exception e) {
            logger.error("importData.error",e);
            restResult.setSuccess(false);
            restResult.setCode(ErrorCode.COMMON_ERROR);
            restResult.setMsg("导入失败，原因:" + e.getMessage());
        }

        return restResult;
    }


    /**
     * @description: 下载导入模板
     **/
    @GetMapping("/excelDownloadTemp")
    public void excelDownloadTemp(HttpServletResponse response,@RequestParam Map<String, String> reqData) {
        service.excelDownloadTemp(response,reqData, null);
    }

    /**
     * @description: excel导入数据
     **/
    @RequestMapping(value = "/excelImport", method = RequestMethod.POST)
    public RestResult excelImport(@RequestParam(value = "file") MultipartFile file, @RequestParam Map<String, String> reqData) {
        return  RestResult.ok(service.excelImport(file,reqData));
    }


    // 校验属性设置
    public void setBatchCheck(String idValue,String field,Object valueNew) {
    }

    /**
     * 批量设置属性
     */
    @PostMapping("/setBatch")
//    @ThreadLock(busType = "批量设置属性")
    public RestResult setBatch(@RequestBody E entity,@RequestBody Map<String, String> reqData) {
        List<String> idList = ListUtil.toList(reqData.get("idListJoin").split(","));
        List<String> fieldList = ListUtil.toList(reqData.get("fieldListJoin").split(","));
        if (idList == null || idList.isEmpty()) {
            return RestResult.error("缺少参数[idListJoin]");
        }
        if (fieldList == null || fieldList.isEmpty()) {
            return RestResult.error("缺少参数[fieldListJoin]");
        }

        Collection<E> entityList =  service.listByIds(idList);
        if (entityList == null || entityList.isEmpty()) {
            return RestResult.error("所操作的数据已删除,请刷新");
        }

        Object ojbValue = null;
        UpdateWrapper updateWrapper;
        String idValue = null;
        for(E obj : entityList) {
            updateWrapper =Wrappers.update();
            idValue = ReflectUtil.getFieldValue(obj, "id") +"";
            updateWrapper.eq("id", idValue);
            updateWrapper.set("gmt_modified", DateUtils.format(DateUtils.now(),DateUtils.YYYYMMDDHHMMSS_PATTER2));
            updateWrapper.set("modifier", UserUtils.currentUser().getCode());
            for(String field : fieldList) {
                ojbValue = ReflectUtil.getFieldValue(entity, field);
                if (ojbValue != null) {
                    setBatchCheck(idValue, field, ojbValue);
                    updateWrapper.set(StringUtils.camelToUnderline(field,1),ojbValue);
                }
            }
            service.update(updateWrapper);
        }
        return RestResult.ok("批量设置成功");
    }

}
